home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / telecomm / archivers / aucode.lha / AuCode.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-06  |  16.8 KB  |  348 lines

  1. #ifndef AuCode_H
  2. #define AuCode_H
  3. /* -------------------------------------------------------------------------- **
  4.  * AuCode.h - Amiga uuencode/uudecode toolkit.
  5.  *
  6.  *  Written by Christopher R. Hertel; December, 1992
  7.  *  email: crh@bubble.mooses.affinity.mn.org
  8.  * -------------------------------------------------------------------------- **
  9.  *  Copyright (C) 1993 Christopher R. Hertel
  10.  *
  11.  *  This library is free software; you can redistribute it and/or
  12.  *  modify it under the terms of the GNU Library General Public
  13.  *  License as published by the Free Software Foundation; either
  14.  *  version 2 of the License, or (at your option) any later version.
  15.  *
  16.  *  This library is distributed in the hope that it will be useful,
  17.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19.  *  Library General Public License for more details.
  20.  *
  21.  *  You should have received a copy of the GNU Library General Public
  22.  *  License along with this library; if not, write to the Free
  23.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  *
  25.  * -------------------------------------------------------------------------- **
  26.  *
  27.  * $Log:    AuCode.h,v $
  28.  * Revision 1.3  94/02/06  14:09:39  CRH
  29.  * With this revision I rewrote the comments for functions Cleanln() and 
  30.  * Decodeln().  I fixed some bugs with the checksum calculations (I was
  31.  * getting negative values), and I added an internal function to calculate
  32.  * checksums on bytes triples (au_cdChecksum3()).  CRH
  33.  * 
  34.  * Revision 1.2  93/09/15  21:29:22  CRH
  35.  * Fixed a small bug in the decoding functions.  Plus some general
  36.  * cleanup.
  37.  *
  38.  * Revision 1.1  93/03/25  11:31:56  CRH
  39.  * Cleaned up comments.  Clarified License and Copyright.
  40.  *
  41.  * Revision 1.0  93/03/04  00:29:07  CRH
  42.  * Initial revision
  43.  *
  44.  * -------------------------------------------------------------------------- **
  45.  * My understanding of uuencoding/decoding is based on the knowledge that I
  46.  * gained by reading the uuencode source provided with AmigaUUCP V1.16.
  47.  * Many thanks to the authors of that software!  The following are comments
  48.  * from their code, which are included as my way of giving credit where
  49.  * credit is due.
  50.  *
  51.  * /begin/
  52.  * [uuencode.c:]
  53.  * Written by Mark Horton
  54.  * Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums
  55.  * Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
  56.  * compatibility
  57.  * Modified by bcn (Bryce Nesbitt,ucbvax!hoser!bryce) to enable CTRL-C for
  58.  * Amiga Lattice C.  Added a transparent file size trailer for later check.
  59.  * Changed fopen from "r" to "rb" for Messy-dos machines (thanks to Andrew
  60.  * Wylie)
  61.  *
  62.  * [uudecode.c:]
  63.  * Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix a misleading
  64.  * error message on the Amiga port, to fix a bug that prevented decoding
  65.  * certain files, to work even if trailing spaces have been removed from a
  66.  * file, to check the filesize (if present), to add some error checking, to
  67.  * loop for multiple decodes from a single file, and to handle common
  68.  * BITNET mangling.  Kludged around a missing string function in Aztec
  69.  * C. Changed "r" to "rb" and "w" to "wb" for Messy-dos machines
  70.  * (Thanks to Andrew Wylie).
  71.  * /end/
  72.  *
  73.  * -------------------------------------------------------------------------- **
  74.  *  Initial comments:  This module implements the basic uuencode/decode
  75.  *  functionality.  The functions are designed to be reentrant, so you may
  76.  *  use them as part of either a link library or a run-time library.
  77.  *  Also, no attempt is made to support any hardware platform other than the
  78.  *  Commodore Amiga.  In particular, this module is written to compile under
  79.  *  SAS C 5.10 or above on an Amiga running OS 2.04 or above.  The code is,
  80.  *  however, written in a fairly generic style, and should be highly porable.
  81.  *
  82.  *  Notes regarding style:  I am a Pascal programmer at heart, and most of
  83.  *  my style choices are based on my preference for that language and its
  84.  *  derivatives.  The result is a hybrid format with a few odd quirks of
  85.  *  its own.  In any case, I intend to produce several modules, so my
  86.  *  function, macro, constant, variable, and type naming conventions serve
  87.  *  to associate identifiers with modules, and to prevent duplicate names
  88.  *  (after all, who else would use such awkward identifiers?).
  89.  *
  90.  *  As mentioned above, these modules are designed to work within the
  91.  *  multitasking environment of the Commodore Amiga.  The code is (should
  92.  *  be) reentrant and self contained (I've even avoided ANSI standard
  93.  *  functions, because the available libraries are not necessarily
  94.  *  reentrant).  I have, however, been careful to avoid Amiga-specific
  95.  *  functions.  It should, therefore, be very easy to port the code to other
  96.  *  platforms.  (I'm hoping for a microVAX for Christmas. ;-) )
  97.  *
  98.  * Christopher R. Hertel; December, 1992
  99.  * -------------------------------------------------------------------------- **
  100.  */
  101.  
  102. /* -------------------------------------------------------------------------- **
  103.  * Defines...
  104.  *  au_cdMAXPhrase -  a "phrase" of input becomes one line of output.  In
  105.  *                    other words, function AuEncode() will encode at most
  106.  *                    MAXphrase characters at a time, and write them to the
  107.  *                    output buffer. The output line length will be 8/6ths
  108.  *                    (or 1 and 1/3 times) the original input, plus three
  109.  *                    extra bytes per line (length, checksum, and newline).
  110.  *                    This value should ALWAYS be a multiple of three!
  111.  *                    Encoding is performed three bytes at a time.  Other
  112.  *                    values will cause a reducion in performance and some
  113.  *                    oddly encoded (yet correct) translations. This value
  114.  *                    should also ALWAYS be less than 64, because it will
  115.  *                    be encoded in six bits just like everything else.
  116.  *
  117.  *  au_cdCHKSUMsize - Checksum size, in decimal.  A checksum of n indicates
  118.  *                    that the checksum should be in the range 0..(n-1), so
  119.  *                    if n = 64, then the checksum would be in the range
  120.  *                    0..63 (i.e., six bits).
  121.  *
  122.  *  au_cdMAX_LINE   - This is, roughly, the maximum length (in bytes) of a
  123.  *                    "line".  A line being a single uuencode "record", so
  124.  *                    to speak.  The value is calculated as follows:  The
  125.  *                    number of source bytes must be <=63 (since only six
  126.  *                    bits are used to store this value).  63 bytes encodes
  127.  *                    to (63 * (4 / 3)) == 84 bytes.
  128.  *
  129.  *                    Add:
  130.  *                        + one byte for the encoded length
  131.  *                        + one for the encoded checksum
  132.  *                        + one for the eoln character
  133.  *                        + one more, for a nul terminator
  134.  *
  135.  *                    Total 88.  Add 2 for good luck for a total of 90.
  136.  *                    (I was once told that infinity was "as much as you'll
  137.  *                    ever need plus one".)
  138.  *
  139.  */
  140.  
  141. #define au_cdMAXPhrase  45
  142. #define au_cdCHKSUMsize 64
  143. #define au_cdMAX_LINE   90
  144.  
  145. /* -------------------------------------------------------------------------- **
  146.  * Defined Error Codes...
  147.  *
  148.  *          au_cdErr_NoError  - No error.
  149.  *
  150.  *          au_cdErr_Cramped  - Output buffer does not contain enough space.
  151.  *
  152.  *          au_cdErr_Checksum - The checksum comparison failed.
  153.  */
  154. #define au_cdErr_NoError  0x00
  155. #define au_cdErr_Cramped  0x01
  156. #define au_cdErr_Checksum 0x02
  157.  
  158. /* -------------------------------------------------------------------------- **
  159.  * Macros...
  160.  *  au_cdENCD - encode a character.  The character, c, is encoded in a six
  161.  *              bit field as follows:  If c is not nul, the lower six bits
  162.  *              arithmatically added to the value of the space character
  163.  *              (ascii 32).  If c *is* nul, then the value of the `
  164.  *              character is returned.  (Note: octal 77 = hex 3F = binary
  165.  *              00111111.)
  166.  *
  167.  *  au_cdDECD - decode a character.  Subtract the value of the space
  168.  *              character, then make sure that you have only the lower six
  169.  *              bits.
  170.  *
  171.  *  au_cdExpPhrLen-Given the length of a source phrase, calculate the
  172.  *              number of bytes required for the encoded line.  This macro
  173.  *              converts the number of source bytes into bits, then figures
  174.  *              out how many bytes are required to store the encoded
  175.  *              version (rounding up any fractional part to a whole
  176.  *              number).  Three bytes are then added to the count (for
  177.  *              length, checksum, and newline).  Note that the entire
  178.  *              calculation is performed using integers.
  179.  *
  180.  *  au_cdCleanSixel-A potential error exists because BITNET converts the
  181.  *              "^" to a "~".  Technically, the "~" (tilde) can't be part
  182.  *              of the code, so it's safe to convert it back to "^" (carat)
  183.  *              using this macro.
  184.  *
  185.  */
  186.  
  187. #define au_cdENCD(c) ((c) ? (((c) & 077) + ' ') : '`')  /* single char encode */
  188.  
  189. #define au_cdDECD(c) (((c) - ' ') & 077)           /* single character decode */
  190.  
  191. #define au_cdExpPhrLen(pl) (((((pl) * 80) / 6)+9)/10 +3)
  192.  
  193. #define au_cdCleanSixel(c) (('~'==(c))?'^':(c))
  194.  
  195. /* -------------------------------------------------------------------------- **
  196.  * Functions Prototypes...
  197.  */
  198.  
  199. int au_cdCvt3to4( char *S, char *T );
  200.   /* ------------------------------------------------------------------------ **
  201.    * Uuencode a three-byte value.  The result is a four-byte value.  The
  202.    * function returns the checksum of the three source bytes.
  203.    *
  204.    *  Input:
  205.    *    S - A pointer to an array of three bytes.  These are the source data.
  206.    *    T - A pointer to the four byte target array.
  207.    *
  208.    *  Output: a checksum value calculated from the three source bytes.
  209.    * ------------------------------------------------------------------------ **
  210.    */
  211.  
  212. int au_cdCvt4to3( char *S, char *T );
  213.   /* ------------------------------------------------------------------------ **
  214.    * Uudecode a four-byte value.  The result is a three-byte value.  The
  215.    * function returns the checksum of the three target bytes.
  216.    *
  217.    *  Input:
  218.    *    S - A pointer to an array of four bytes.  These are the source data.
  219.    *    T - A pointer to the three byte target array.
  220.    *
  221.    *  Output: a checksum value calculated from the three target bytes.
  222.    * ------------------------------------------------------------------------ **
  223.    */
  224.  
  225. int au_cdEncode( char *sBufr, int sbSize, char *tBufr, int tbSize );
  226.   /* ------------------------------------------------------------------------ **
  227.    * Encode a block of characters using the UUENCODE coding scheme.
  228.    *
  229.    *  Input:
  230.    *    sBufr   - A pointer to a buffer containing the bytes to be encoded.
  231.    *    sbSize  - The number of bytes in sBufr to be encoded.
  232.    *    tBufr   - A pointer to the target buffer.
  233.    *    tbSize  - The number of bytes available in tBufr.
  234.    *
  235.    *  Output:   The number of source bytes that were actually converted.  If
  236.    *            this number is less than sbSize, an error occured during the
  237.    *            encoding process (ran out of room in tBufr).  The best way to
  238.    *            recover is to write out the contents of tBufr (which, if they
  239.    *            exist, are valid) and call this function again, passing in a
  240.    *            pointer to the remainder of the source bytes.
  241.    *         -> However, if zero bytes were processed (i.e., this function
  242.    *            returns zero), then tBufr is simply not large enough.
  243.    *
  244.    *  Note:     This function will not write the terminating line.
  245.    * ------------------------------------------------------------------------ **
  246.    */
  247.  
  248. int au_cdCleanln( char *sBufr, int sbSize, char *tBufr, int tbSize );
  249.   /* ------------------------------------------------------------------------ **
  250.    * Clean a line of input to ensure that it can be decoded properly.
  251.    *
  252.    *  Input:  sBufr   - A pointer to an array of encoded bytes.  The
  253.    *                    contents of sBufr[] (the "source") are assumed to
  254.    *                    be a single line of uuencoded text.  The line is
  255.    *                    considered to be terminated by ascii value less
  256.    *                    than 32.
  257.    *
  258.    *          sbSize  - The number of significant bytes in sBufr[].  That
  259.    *                    is, the maximum number of bytes that you wish to
  260.    *                    have cleaned.  Cleanln() will process no more than
  261.    *                    min( tbSize, sbSize ) bytes.
  262.    *
  263.    *          tBufr   - A pointer to the target buffer.  The target buffer
  264.    *                    will receive the "cleaned" copy of the source line.
  265.    *                    Note that, in general, tBufr should be at least
  266.    *                    sbSize bytes long, and possibly longer.  It should
  267.    *                    always be safe to create a tBufr that is
  268.    *                    au_cdMAX_LINE bytes long (unless you are using in
  269.    *                    this module in some new and interesting way that is
  270.    *                    beyond my ability to extrapolate).
  271.    *
  272.    *          tbSize  - The number of bytes available in tBufr.  Cleanln()
  273.    *                    will process no more than min( tbSize, sbSize )
  274.    *                    bytes.
  275.    *
  276.    *  Output: The number of characters in sBufr[] that were copied to
  277.    *          tBufr[].  This value does not include any spaces that were
  278.    *          added to the end of tBufr[] as padding.
  279.    *
  280.    *  Notes:  The input line is "cleaned" as follows:
  281.    *
  282.    *          This function copies the input line to a new buffer.  During
  283.    *          the copy the function repairs damage that *may* have occurred
  284.    *          during transmission.
  285.    *
  286.    *          In particular, some UUENCODErs encode a nul sixel as a space
  287.    *          (this module encodes a nul as a "`" character, both decode
  288.    *          to the same thing).  Some editors (and other text utilites)
  289.    *          will trim trailing spaces from the ends of lines.  This
  290.    *          function pads the end of the target buffer with spaces to
  291.    *          avoid the problem of lost sixles.
  292.    *
  293.    *          Another potential error exists because BITNET converts the
  294.    *          "^" to a "~".  Technically, the "~" can't be part of the code,
  295.    *          so it's safe to convert it back using the au_cdCleanSixel()
  296.    *          macro.
  297.    *
  298.    *          This function always places a nul byte in the last position
  299.    *          in tBufr[].  That is:
  300.    *              tBufr[tbSize-1] = '\0';
  301.    *          be certain that your tBufr[] is big enough to handle all the
  302.    *          valid characters in sBufr[] plus the nul!
  303.    * ------------------------------------------------------------------------ **
  304.    */
  305.  
  306. int au_cdDecodeln( char *sBufr, char *tBufr, int tbSize, int *ErrCD );
  307.   /* ------------------------------------------------------------------------ **
  308.    * This function will decode one "line" of encoded input.
  309.    *
  310.    *  Input:  sBufr   - A pointer to a buffer containing the encoded data
  311.    *                    that is to be decoded.  The data should be in the
  312.    *                    form of a "line" of uuencoded text.  The line is
  313.    *                    assumed to be "clean" (see au_cdCleanln()).
  314.    *          tBufr   - A pointer to the target buffer.  tBufr[] will
  315.    *                    receive the decoded data.
  316.    *          tbSize  - Number of bytes available in tBufr[].
  317.    *          ErrCD   - A pointer to an integer that will receive an
  318.    *                    error code.  Check *ErrCD for one of the following
  319.    *                    values:
  320.    *
  321.    *                    au_cdErr_NoError  - No error.  If the function
  322.    *                      return value is zero *and* the error code is
  323.    *                      _NoError, then an empty (i.e., terminating) line
  324.    *                      has been found, indicating end of the (encoded)
  325.    *                      file.
  326.    *
  327.    *                    au_cdErr_Cramped  - tBufr[] does not contain enough
  328.    *                      space to receive the decoded information.  A
  329.    *                      single encoded line may contain, at most, 63
  330.    *                      encoded (source) bytes.
  331.    *
  332.    *                    au_cdErr_Checksum - the checksum comparison failed.
  333.    *                      Either the source line is mangled, or the
  334.    *                      checksum was not written properly by the encoding
  335.    *                      program.
  336.    *
  337.    *  Output: The number of bytes that were generated as a result of
  338.    *          decoding the input line.
  339.    *
  340.    *  Notes: sBufr[] is assumed to be "clean".  See the notes associated
  341.    *  with function au_cdCleanln() for an explanation of the term "clean",
  342.    *  as used in this context.
  343.    * ------------------------------------------------------------------------ **
  344.    */
  345.  
  346. /* ========================================================================== */
  347. #endif /* AuCode_H */
  348.